package com.flyme.module.base.provider.api;

import com.alibaba.fastjson.JSONObject;
import com.egzosn.pay.ali.api.AliPayService;
import com.egzosn.pay.ali.bean.AliTransactionType;
import com.egzosn.pay.common.api.PayConfigStorage;
import com.egzosn.pay.common.api.PayService;
import com.egzosn.pay.common.bean.*;
import com.egzosn.pay.common.http.UriVariables;
import com.egzosn.pay.common.util.MatrixToImageWriter;
import com.egzosn.pay.common.util.str.StringUtils;
import com.egzosn.pay.wx.bean.WxTransactionType;
import com.flyme.common.core.model.ResultBody;
import com.flyme.common.core.model.query.CriteriaQuery;
import com.flyme.common.core.utils.ObjectUtils;
import com.flyme.module.base.provider.CxPayUtil;
import com.flyme.module.base.provider.service.SysBalanceService;
import com.flyme.module.base.provider.service.SysUserexaminationService;
import com.flyme.module.file.provider.service.SysCourseEnrollService;
import com.flyme.module.order.client.entity.Order;
import com.flyme.module.order.client.entity.PayAccount;
import com.flyme.module.order.client.enums.OrderStatusEnum;
import com.flyme.module.order.client.enums.PayTypeEnum;
import com.flyme.module.order.client.vo.PayType;
import com.flyme.module.order.client.vo.QueryOrder;
import com.flyme.module.order.provider.service.OrderService;
import com.flyme.module.order.provider.service.PayAccountService;
import com.flyme.module.order.provider.service.PayResponse;
import com.flyme.module.order.provider.unionpay.ZSHttpRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.Map;
import java.util.UUID;

/**
 * 支付控制器
 */
@RestController
@RequestMapping("/pay")
@Slf4j
public class PayController {

    @Resource
    private AutowireCapableBeanFactory spring;

    @Autowired
    private PayAccountService service;
    @Autowired
    private OrderService orderService;
    @Autowired
    private SysBalanceService balanceService;
    @Autowired
    private SysCourseEnrollService courseenrollService;
    @Autowired
    private SysUserexaminationService sysUserexaminationService;


    /**
     * 跳到支付页面 针对实时支付,即时付款
     */
    @RequestMapping(value = "toPay.html", produces = "text/html;charset=UTF-8")
    public String toPay(HttpServletRequest request, String transactionType, String bankType, BigDecimal price) {
        // 获取对应的支付账户操作工具（可根据账户id）
        PayResponse payResponse = service.getPayResponse(request);

        PayOrder order = new PayOrder("订单title", "摘要", null == price ? new BigDecimal(0.01) : price, UUID.randomUUID().toString().replace("-", ""), PayType.valueOf(payResponse.getStorage().getPayType()).getTransactionType(transactionType));
        // ------ 微信H5使用----
        order.setSpbillCreateIp(request.getHeader("X-Real-IP"));
        StringBuffer requestURL = request.getRequestURL();
        // 设置网页地址
        order.setWapUrl(requestURL.substring(0, requestURL.indexOf("/") > 0 ? requestURL.indexOf("/") : requestURL.length()));
        // 设置网页名称
        order.setWapName("在线充值");
        // ------ 微信H5使用----

        // 此处只有刷卡支付(银行卡支付)时需要
        if (StringUtils.isNotEmpty(bankType)) {
            order.setBankType(bankType);
        }
        Map<String, Object> orderInfo = payResponse.getService().orderInfo(order);
        return payResponse.getService().buildRequest(orderInfo, MethodType.POST);
    }

    /**
     * 跳到支付页面 针对实时支付,即时付款
     */
    @RequestMapping(value = "toWxPay.html", produces = "text/html;charset=UTF-8")
    public String toWxPay(HttpServletRequest request) {
        // 获取对应的支付账户操作工具（可根据账户id）
        PayResponse payResponse = service.getPayResponse(request);
        PayOrder order = new PayOrder("订单title", "摘要", new BigDecimal(0.01), UUID.randomUUID().toString().replace("-", ""), WxTransactionType.MWEB);
        order.setSpbillCreateIp(request.getHeader("X-Real-IP"));
        StringBuffer requestURL = request.getRequestURL();
        // 设置网页地址
        order.setWapUrl(requestURL.substring(0, requestURL.indexOf("/") > 0 ? requestURL.indexOf("/") : requestURL.length()));
        // 设置网页名称
        order.setWapName("在线充值");
        Map<String, Object> orderInfo = payResponse.getService().orderInfo(order);
        return payResponse.getService().buildRequest(orderInfo, MethodType.POST);
    }

    /**
     * 公众号支付
     */
    @RequestMapping(value = "weChatPay")
    public ResultBody weChatPay(HttpServletRequest request, String openid, BigDecimal price) {
        String orderId = request.getParameter("orderId");//订单id
        Order order = orderService.getById(orderId);
        order.setOutTradeNo(UUID.randomUUID().toString().replaceAll("-",""));
        orderService.saveOrUpdate(order);
        if (ObjectUtils.isEmpty(order)||!order.getOrderStatus().equals(OrderStatusEnum.unpaid)) {
            return ResultBody.failed("该订单非待支付订单，不能支付");
        }
        CriteriaQuery qw=new CriteriaQuery();
        qw.select("partner,appId,publicKey,privateKey,notifyUrl,returnUrl,seller,signType,inputCharset,isTest");
        qw.eq("id","2");
        PayAccount a=service.getOne(qw);
        CxPayUtil cxPayUtil=new CxPayUtil();
       return  cxPayUtil.cx_recharge(request,a,openid,order);
    }





    /**
     * 刷卡付,pos主动扫码付款(条码付)
     */
    @RequestMapping(value = "microPay")
    public Map<String, Object> microPay(HttpServletRequest request, String transactionType, BigDecimal price, String authCode) throws IOException {
        // 获取对应的支付账户操作工具（可根据账户id）
        PayResponse payResponse = service.getPayResponse(request);
        PayOrder order = new PayOrder("huodull order", "huodull order", null == price ? new BigDecimal(0.01) : price, UUID.randomUUID().toString().replace("-", ""), PayType.valueOf(payResponse.getStorage().getPayType()).getTransactionType(transactionType));
        // 设置授权码，条码等
        order.setAuthCode(authCode);
        // 支付结果
        Map<String, Object> params = payResponse.getService().microPay(order);
        PayConfigStorage storage = payResponse.getService().getPayConfigStorage();
        // 校验
        if (payResponse.getService().verify(params)) {
            PayMessage message = new PayMessage(params, storage.getPayType(), storage.getMsgType().name());
            // 支付校验通过后的处理
            payResponse.getRouter().route(message);
        }
        // 这里开发者自行处理
        return params;
    }


    /**
     * 获取一码付二维码图像 二维码支付
     */
    @RequestMapping(value = "toWxAliQrPay", produces = "image/jpeg;charset=UTF-8")
    public byte[] toWxAliQrPay(String wxPayId, String aliPayId, BigDecimal price, HttpServletRequest request) throws IOException {
        // 获取对应的支付账户操作工具（可根据账户id）
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        // 这里为需要生成二维码的地址
        StringBuffer url = request.getRequestURL();
        url = new StringBuffer(url.substring(0, url.lastIndexOf(request.getRequestURI())));
        url.append("/toWxAliPay?");
        if (null != wxPayId) {
            url.append("wxPayId=").append(wxPayId).append("&");
        }
        if (null != aliPayId) {
            url.append("aliPayId=").append(aliPayId).append("&");
        }
        url.append("price=").append(price);

        ImageIO.write(MatrixToImageWriter.writeInfoToJpgBuff(url.toString()), "JPEG", baos);
        return baos.toByteArray();
    }



    /**
     * 支付宝与微信平台的判断 并进行支付的转跳
     */
    @RequestMapping(value = "toWxAliPay", produces = "text/html;charset=UTF-8")
    public String toWxAliPay(Integer wxPayId, Integer aliPayId, BigDecimal price, HttpServletRequest request) throws IOException {
        StringBuilder html = new StringBuilder();
        // 订单
        PayOrder payOrder = new PayOrder("订单title", "摘要", null == price ? new BigDecimal(0.01) : price, System.currentTimeMillis() + "");
        String ua = request.getHeader("user-agent");
        if (ua.contains("MicroMessenger")) {
            payOrder.setTransactionType(WxTransactionType.NATIVE);
            PayService<?> service = this.service.getPayResponse(request).getService();
            return String.format("<script type=\"text/javascript\">location.href=\"%s\"</script>", (String) service.orderInfo(payOrder).get("code_url"));
        }
        if (ua.contains("AlipayClient")) {
            payOrder.setTransactionType(AliTransactionType.SWEEPPAY);
            AliPayService service = (AliPayService) this.service.getPayResponse(request).getService();
            JSONObject result = service.getHttpRequestTemplate().postForObject(service.getReqUrl() + "?" + UriVariables.getMapToParameters(service.orderInfo(payOrder)), null, JSONObject.class);
            result = result.getJSONObject("alipay_trade_precreate_response");
            return String.format("<script type=\"text/javascript\">location.href=\"%s\"</script>", result.getString("qr_code"));
        }
        return String.format("<script type=\"text/javascript\">alert(\"请使用微信或者支付宝App扫码%s\");window.close();</script>", ua);

    }

    /**
     * app支付获取支付预订单信息（统一下单）
     */
    @RequestMapping("getPayInfo")
    public ResultBody getOrderInfo(HttpServletRequest request) {
        String payCode = request.getParameter("payCode");//支付方式
        String orderId = request.getParameter("orderId");//订单id
        Order order = orderService.getById(orderId);
        if (!order.getOrderStatus().equals(OrderStatusEnum.unpaid)) {
            return ResultBody.failed("该订单非待支付订单，不能支付");
        }
        orderService.editOrder(UUID.randomUUID().toString().replace("-", ""), orderId, payCode);// 更新订单的第三方流水号
        if (PayTypeEnum.offline.code.equals(payCode) || PayTypeEnum.Balance.code.equals(payCode)) {
            return balanceService.payBack(orderId, payCode);
        }
        PayResponse payResponse = service.getPayResponse(request);
        return ResultBody.success(payResponse.getPayInfo());
    }



    /**
     * 支付回调地址 方式一
     */
    @RequestMapping(value = "payBackOne{orderId}.json")
    public String payBackOne(HttpServletRequest request, @PathVariable String orderId) throws IOException {
        // 根据账户id，获取对应的支付账户操作工具
        Order order = orderService.getById(orderId);
        PayResponse payResponse = service.getPayCallBackResponse(request, order);
        PayConfigStorage storage = payResponse.getStorage();
        PayService<?> se = payResponse.getService();

        Map<String, Object> params = se.getParameter2Map(request.getParameterMap(), request.getInputStream());
        // Map<String, Object> params =
        // JSONObject.parseObject("{\"bizType\":\"000201\",\"signPubKeyCert\":\"-----BEGIN
        // CERTIFICATE-----\\r\\nMIIEQzCCAyugAwIBAgIFEBJJZVgwDQYJKoZIhvcNAQEFBQAwWDELMAkGA1UEBhMC\\r\\nQ04xMDAuBgNVBAoTJ0NoaW5hIEZpbmFuY2lhbCBDZXJ0aWZpY2F0aW9uIEF1dGhv\\r\\ncml0eTEXMBUGA1UEAxMOQ0ZDQSBURVNUIE9DQTEwHhcNMTcxMTAxMDcyNDA4WhcN\\r\\nMjAxMTAxMDcyNDA4WjB3MQswCQYDVQQGEwJjbjESMBAGA1UEChMJQ0ZDQSBPQ0Ex\\r\\nMQ4wDAYDVQQLEwVDVVBSQTEUMBIGA1UECxMLRW50ZXJwcmlzZXMxLjAsBgNVBAMU\\r\\nJTA0MUBaMjAxNy0xMS0xQDAwMDQwMDAwOlNJR05AMDAwMDAwMDEwggEiMA0GCSqG\\r\\nSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDDIWO6AESrg+34HgbU9mSpgef0sl6avr1d\\r\\nbD/IjjZYM63SoQi3CZHZUyoyzBKodRzowJrwXmd+hCmdcIfavdvfwi6x+ptJNp9d\\r\\nEtpfEAnJk+4quriQFj1dNiv6uP8ARgn07UMhgdYB7D8aA1j77Yk1ROx7+LFeo7rZ\\r\\nDdde2U1opPxjIqOPqiPno78JMXpFn7LiGPXu75bwY2rYIGEEImnypgiYuW1vo9UO\\r\\nG47NMWTnsIdy68FquPSw5FKp5foL825GNX3oJSZui8d2UDkMLBasf06Jz0JKz5AV\\r\\nblaI+s24/iCfo8r+6WaCs8e6BDkaijJkR/bvRCQeQpbX3V8WoTLVAgMBAAGjgfQw\\r\\ngfEwHwYDVR0jBBgwFoAUz3CdYeudfC6498sCQPcJnf4zdIAwSAYDVR0gBEEwPzA9\\r\\nBghggRyG7yoBATAxMC8GCCsGAQUFBwIBFiNodHRwOi8vd3d3LmNmY2EuY29tLmNu\\r\\nL3VzL3VzLTE0Lmh0bTA5BgNVHR8EMjAwMC6gLKAqhihodHRwOi8vdWNybC5jZmNh\\r\\nLmNvbS5jbi9SU0EvY3JsMjQ4NzIuY3JsMAsGA1UdDwQEAwID6DAdBgNVHQ4EFgQU\\r\\nmQQLyuqYjES7qKO+zOkzEbvdFwgwHQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsGAQUF\\r\\nBwMEMA0GCSqGSIb3DQEBBQUAA4IBAQAujhBuOcuxA+VzoUH84uoFt5aaBM3vGlpW\\r\\nKVMz6BUsLbIpp1ho5h+LaMnxMs6jdXXDh/du8X5SKMaIddiLw7ujZy1LibKy2jYi\\r\\nYYfs3tbZ0ffCKQtv78vCgC+IxUUurALY4w58fRLLdu8u8p9jyRFHsQEwSq+W5+bP\\r\\nMTh2w7cDd9h+6KoCN6AMI1Ly7MxRIhCbNBL9bzaxF9B5GK86ARY7ixkuDCEl4XCF\\r\\nJGxeoye9R46NqZ6AA/k97mJun//gmUjStmb9PUXA59fR5suAB5o/5lBySZ8UXkrI\\r\\npp/iLT8vIl1hNgLh0Ghs7DBSx99I+S3VuUzjHNxL6fGRhlix7Rb8\\r\\n-----END
        // CERTIFICATE-----\",\"orderId\":\"20171213224128\",\"signature\":\"l8xBYSoMNzt01DDa9/JYcrQKWxN5tasUgSxf6NNsQK5t+DqMr2G9qhHXnDg5bEzeRyTFP4bM3htX9RTRhXYDy7EEsL46ZD4ib5I6mp2wXx+26zscUcLdJUiddkY5eFvQK4tPC8blw7Y6p858yiVJpHgbOK3cONhS7vwPJtK2jMbkY+GATu3aZ4iygkQc75cG+EW8nJQVwLNh7q9A6A6II18EFxR7XubdlIHXv/InVaS6ux8Wh2nmQlhRRnLtHq1ri7v1QPlu2FzM+kaf7/fn61iGr8zEPj62NzWDXue62LUfb4kTRgdkcJnfJBJl8vjZ/w93UtsnK3zjzJC/Nu+wCw==\",\"txnSubType\":\"01\",\"traceNo\":\"492156\",\"accNo\":\"6221********0000\",\"settleAmt\":\"1000\",\"settleCurrencyCode\":\"156\",\"settleDate\":\"1213\",\"txnType\":\"01\",\"encoding\":\"UTF-8\",\"version\":\"5.1.0\",\"queryId\":\"511712132241284921568\",\"accessType\":\"0\",\"exchangeRate\":\"0\",\"respMsg\":\"success\",\"traceTime\":\"1213224128\",\"txnTime\":\"20171213224128\",\"merId\":\"777290058154626\",\"currencyCode\":\"156\",\"respCode\":\"00\",\"signMethod\":\"01\",\"txnAmt\":\"1000\"}");

        if (null == params) {
            return payResponse.getService().getPayOutMessage("fail", "失败").toMessage();
        }
        // 校验
        if (payResponse.getService().verify(params)) {
            PayMessage message = new PayMessage(params, storage.getPayType(), storage.getMsgType().name());
            PayOutMessage outMessage = payResponse.getRouter().route(message);
            // PayOutMessage outMessage =
            // payResponse.getService().payBack(request.getParameterMap(),
            // request.getInputStream());
            System.out.println("content^^^^^^^^^^^^^^^^^^^^^^^^^^^^^返回内容：" + outMessage);
            // return outMessage.toMessage();
            return "success";
        }
        return payResponse.getService().getPayOutMessage("fail", "失败").toMessage();
    }

    /**
     * 查询
     */
    @RequestMapping("query")
    public Map<String, Object> query(HttpServletRequest request, QueryOrder order) {
        PayResponse payResponse = service.getPayResponse(request);
        return payResponse.getService().query(order.getTradeNo(), order.getOutTradeNo());
    }
    /**
     * 查询
     *
     * @param order
     *            订单的请求体
     * @return 返回查询回来的结果集，支付方原值返回
     */
    /*
     * @RequestMapping("unionRefundOrConsumeUndo") public Map<String, Object>
     * unionQuery(UnionQueryOrder order,String transactionType) { PayResponse
     * payResponse = feign.getPayResponse(order.getPayId()); UnionPayService
     * feign = (UnionPayService)payResponse.getService();
     *
     * return
     * feign.unionRefundOrConsumeUndo(order,UnionTransactionType.valueOf(
     * transactionType)); }
     */

    /**
     * 交易关闭接口
     */
    @RequestMapping("close")
    public Map<String, Object> close(HttpServletRequest request, QueryOrder order) {
        PayResponse payResponse = service.getPayResponse(request);
        return payResponse.getService().close(order.getTradeNo(), order.getOutTradeNo());
    }

    /**
     * 申请退款接口
     */
    @RequestMapping("refund")
    public Map<String, Object> refund(HttpServletRequest request, RefundOrder order) {
        PayResponse payResponse = service.getPayResponse(request);
        // return payResponse.getService().refund(order.getTradeNo(),
        // order.getOutTradeNo(), order.getRefundAmount(),
        // order.getTotalAmount());
        return payResponse.getService().refund(order);
    }

    /**
     * 查询退款
     */
    @RequestMapping("refundquery")
    public Map<String, Object> refundquery(HttpServletRequest request, QueryOrder order) {
        PayResponse payResponse = service.getPayResponse(request);
        return payResponse.getService().refundquery(order.getTradeNo(), order.getOutTradeNo());
    }

    /**
     * 下载对账单
     */
    @RequestMapping("downloadbill")
    public Object downloadbill(HttpServletRequest request, QueryOrder order) {
        PayResponse payResponse = service.getPayResponse(request);

        return payResponse.getService().downloadbill(order.getBillDate(), order.getBillType());
    }

    /**
     * 通用查询接口，根据 TransactionType 类型进行实现,此接口不包括退款
     */
    @RequestMapping("secondaryInterface")
    public Map<String, Object> secondaryInterface(HttpServletRequest request, QueryOrder order) {
        PayResponse payResponse = service.getPayResponse(request);
        TransactionType type = PayType.valueOf(payResponse.getStorage().getPayType()).getTransactionType(order.getTransactionType());
        return payResponse.getService().secondaryInterface(order.getTradeNoOrBillDate(), order.getOutTradeNoBillType(), type);
    }

    /**
     * 转账
     */
    @RequestMapping("transfer")
    public Map<String, Object> transfer(HttpServletRequest request, TransferOrder order) {
        PayService<?> service = this.service.getPayResponse(request).getService();
        return service.transfer(order);
    }

    /**
     * 转账查询
     */
    @RequestMapping("transferQuery")
    public Map<String, Object> transferQuery(HttpServletRequest request, String outNo, String tradeNo) {
        PayService<?> service = this.service.getPayResponse(request).getService();
        return service.transferQuery(outNo, tradeNo);
    }

    /**
     * 银联支付
     */
    @RequestMapping("unionpay")
    public ResultBody unionpay(HttpServletResponse response, String orderId, String dbtbnk) {
        orderService.editOrder(UUID.randomUUID().toString().replace("-", ""), orderId, PayTypeEnum.Unionpay.code);// 更新订单的第三方流水号
        Order order = orderService.getById(orderId);
        String url = "";
        try {
            ZSHttpRequest request = new ZSHttpRequest();
            // 生成请求报文
            String data = request.getRequestStr(order, dbtbnk);
            // 连接前置机，发送请求报文，获得返回报文
            String result = request.sendRequest(data);
            // 处理返回的结果
            //request.processResult(result);
            url = request.openResult(result).replace("https", "http").replace("u.ebank.cmbchina.com", "121.15.180.72");
            System.out.println("支付页面地址：" + url);
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
        return ResultBody.success(url);
    }


}
